﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading;

using SIMA.Interfaces;
using SIMA.Core.Enums;
using SIMA.Core.Data.Collection;
using SIMA.Entities;

namespace SIMA.Server.Services
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class PerfilServer:ServerBase,IPerfil
    {
        #region Fields

        private static List<IPerfilCallback> subscribers = new List<IPerfilCallback>();
        private static SmartContainer<T_C_Perfil> perfilesSmart;
        public ServiceHost host = null;

        #endregion

        #region Constructor

        public PerfilServer()
            : base()
        {
            Init();
        }

        #endregion

        #region Methods

        #region Private Methods

        private void Init()
        {
            perfilesSmart = new SmartContainer<T_C_Perfil>(false,true);
            perfilesSmart.Inserted += new EventHandler<SIMA.Core.EventArgs.InsertedEventArgs>(perfilesSmart_Inserted);
            perfilesSmart.Deleted += new EventHandler<SIMA.Core.EventArgs.DeletedEventArgs>(perfilesSmart_Deleted);
            perfilesSmart.Updated += new EventHandler<SIMA.Core.EventArgs.UpdatedEventArgs>(perfilesSmart_Updated);
            perfilesSmart.Failed += new EventHandler<SIMA.Core.EventArgs.FailedEventArgs>(perfilesSmart_Failed);
        }
        
        #endregion        

        #region Smart Conainer Event Implementation

        void perfilesSmart_Failed(object sender, SIMA.Core.EventArgs.FailedEventArgs e)
        {
            subscribers.ForEach(delegate(IPerfilCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnError(e);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        void perfilesSmart_Updated(object sender, SIMA.Core.EventArgs.UpdatedEventArgs e)
        {
            subscribers.ForEach(delegate(IPerfilCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnUpdated(e);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        void perfilesSmart_Deleted(object sender, SIMA.Core.EventArgs.DeletedEventArgs e)
        {
            subscribers.ForEach(delegate(IPerfilCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnDeleted(e);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        void perfilesSmart_Inserted(object sender, SIMA.Core.EventArgs.InsertedEventArgs e)
        {
            subscribers.ForEach(delegate(IPerfilCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnInserted(e);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        #endregion

        #region Public Methods

        public void InsertPerfil(T_C_Perfil perfil)
        {
            perfilesSmart.Add(perfil);
        }

        public void UpdatePerfil(T_C_Perfil perfilToUpdate, T_C_Perfil perfilUpdated)
        {
            perfilesSmart.Update(perfilToUpdate, perfilUpdated);
        }

        public void DeletePerfil(T_C_Perfil perfil)
        {
            perfilesSmart.Remove(perfil);
        }

        public void SelectSpecilized(string query, CommandType queryType)
        {
            List<T_C_Perfil> tmpPerfil = perfilesSmart[query, queryType];
            subscribers.ForEach(delegate(IPerfilCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnSelected(tmpPerfil);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        #endregion
        
        #region Override Methods

        public override void Connect()
        {
            using (ServiceHost host = new ServiceHost(typeof(PerfilServer), new Uri("net.tcp://192.168.1.33:18501")))
            {
                host.AddServiceEndpoint(typeof(IPerfil), new NetTcpBinding(), "IPerfilSubscription");
                try
                {
                    host.Open();
                    Thread.Sleep(500);
                    Console.WriteLine("Iniciado el servicio de manejo de perfiles ... OK");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }        

        #endregion

        #region Subscriptions

        public bool Subscribe()
        {
            try
            {
                IPerfilCallback callback = OperationContext.Current.GetCallbackChannel<IPerfilCallback>();
                if (!subscribers.Contains(callback))
                {
                    subscribers.Add(callback);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Unsubscribe()
        {
            try
            {
                IPerfilCallback callback = OperationContext.Current.GetCallbackChannel<IPerfilCallback>();
                if (subscribers.Contains(callback))
                {
                    subscribers.Remove(callback);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #endregion
    }
}
